//
//  UIImage+Auxiliary.swift
//  Swift-Extension
//
//  Created by tianXin on 2017/7/21.
//  Copyright © 2017年 田鑫. All rights reserved.
//

import Foundation
import UIKit

enum GradientType {
    case topToBottom,     //从上到小
         leftToRight,     //从左到右
         upleftToLowright,//左上到右下
         uprightToLowleft //右上到左下
}

extension UIImage {
    
    func image(_ color: UIColor) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        guard let context = UIGraphicsGetCurrentContext(), let cgImage = cgImage else {
            return nil
        }
        context.translateBy(x: 0, y: size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.setBlendMode(.normal)
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        context.clip(to: rect, mask: cgImage)
        color.setFill()
        context.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    static func image(_ color: UIColor) -> UIImage? {
        let rect = CGRect(x: 0, y: 0, width: 1.0, height: 1.0)
        UIGraphicsBeginImageContext(rect.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        context.setFillColor(color.cgColor)
        context.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    static func generateImage(_ image: UIImage , size: CGSize) -> UIImage? {
        
        if image.size.height > size.height || image.size.width > size.width {
            return image
        }
        let scale = UIScreen.main.scale
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContext(CGSize(width: size.width*scale, height: size.height*scale))
        guard let context = UIGraphicsGetCurrentContext() else {
          return image
        }
        context.scaleBy(x: scale, y: scale)
        context.fill(rect)
        let point = CGPoint(x: size.width - image.size.width/2, y: size.width - image.size.height/2)
        image.draw(in: CGRect(x: point.x, y: point.y, width: image.size.width, height: image.size.height))
        guard let croppedImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return image;
        }
        UIGraphicsEndImageContext()
        return UIImage.init(cgImage: (croppedImage.cgImage)!, scale: scale, orientation: .up)
    }
    
    static func scaleImage(_ image: UIImage ,size: CGSize) -> UIImage? {
        UIGraphicsBeginImageContext(size)
        image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let scaleImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return scaleImage;
    }
    
    /// Change the size of the image to facilitate uploading the server
    ///
    /// - Parameter size: scale size
    /// - Returns: UIImage
    func scaleImage(_ size: CGSize) -> UIImage? {
        
        let scale = UIScreen.main.scale
        var width  = CGFloat((self.cgImage?.width)!)
        var height = CGFloat((self.cgImage?.height)!)
        let verticalRadio = size.height/height
        let horizontalRadion = size.width/width
        var radion : CGFloat = 1.0
        if verticalRadio > 1 && horizontalRadion > 1 {
            radion = verticalRadio > horizontalRadion ? horizontalRadion : verticalRadio
        }else {
            radion = verticalRadio < horizontalRadion ? verticalRadio : horizontalRadion
        }
        
        width = radion * width
        height = radion * height
        
        let xPos = (size.width - width)/2
        let yPos = (size.height - height)/2
        
        UIGraphicsBeginImageContext(CGSize(width: width*scale, height: height*scale))
        guard let context = UIGraphicsGetCurrentContext() else {
            return self;
        }
        context.scaleBy(x: scale, y: scale)
        self.draw(in: CGRect(x: xPos, y: yPos, width: width, height: height))
        let scaleImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return UIImage.init(cgImage:(scaleImage?.cgImage)! , scale: scale, orientation: .up)
    }
    
    
    /// Keep the original aspect ratio to generate a thumbnail
    ///
    /// - Parameters:
    ///   - image: image
    ///   - size: size
    /// - Returns: UIImage
    static func thumbnailImageOutScale(_ image: UIImage , size: CGSize) -> UIImage? {
        
        let oldSize = image.size
        var rect : CGRect = CGRect.zero
        if size.width/size.height > oldSize.width/oldSize.height {
            rect = CGRect(x: (size.width - size.height*oldSize.width/oldSize.height)/2, y: 0, width: size.height*oldSize.width/oldSize.height, height: size.height)
        }else {
            rect = CGRect(x: 0, y: (size.height - size.width*oldSize.height/oldSize.width)/2, width: size.width, height: size.width*oldSize.height/oldSize.width)
        }
        UIGraphicsBeginImageContext(rect.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return image
        }
        context.setFillColor(UIColor.clear.cgColor)
        UIRectFill(CGRect(x: 0, y: 0, width: rect.width, height: rect.height))
        image.draw(in: CGRect(x: 0, y: 0, width: rect.width, height: rect.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }

    func imageByView(_ view: UIView) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(view.size, view.isOpaque, 0.0)
        guard let context = UIGraphicsGetCurrentContext()   else {
            return nil
        }
        view.layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    func imageAtRect(_ rect: CGRect) -> UIImage? {
     
        guard let cgImage = self.cgImage , let imageRef = cgImage.cropping(to: rect) else {
            return self;
        }
        let image = UIImage.init(cgImage: imageRef)
        return image
    }
    
    
    /// Round cut
    ///
    /// - Parameter size: size
    /// - Returns: UIImage
    func circleImage(size : CGSize) -> UIImage? {
        
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        guard let context = UIGraphicsGetCurrentContext() else {
            return self
        }
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        context.addEllipse(in: rect)
        context.clip()
        self.draw(in: rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    
    /// Linear gradient
    ///
    /// - Parameters:
    ///   - colors: [UIColor]
    ///   - gradientType: GradientType
    ///   - size: size
    /// - Returns: UIImage
    static func gradientColorImageFrameColors(_ colors :[UIColor] , gradientType : GradientType , size :CGSize) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, true, 1)
        guard  let context = UIGraphicsGetCurrentContext() , let compoents:[CGFloat] = UIImage.getCFArray(colors) else {
            return nil
        }
        context.saveGState()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let locations:[CGFloat] = [0,1,1]
        let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents, locations: locations, count: locations.count)
        
        let start : CGPoint!
        let end : CGPoint!
        switch gradientType {
        case .topToBottom:
             start = CGPoint(x: 0, y: 0)
             end = CGPoint(x: 0, y: size.height)
        case .leftToRight:
             start = CGPoint(x: 0, y: 0)
             end = CGPoint(x: size.width, y: 0)
        case .upleftToLowright:
            start = CGPoint(x: 0, y: 0)
            end = CGPoint(x: size.width, y: size.height)
        default:
            start = CGPoint(x: size.width, y: 0)
            end = CGPoint(x: 0, y: size.height)
            break
        }
        context.drawLinearGradient(gradient!, start: start, end: end, options: [.drawsBeforeStartLocation,.drawsAfterEndLocation])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    fileprivate  static func getCFArray(_ colors: [UIColor]) -> [CGFloat]? {
        guard let startColor = colors.first, let endColor = colors.last else {
            return nil
        }
        var sr: CGFloat = 0, sg: CGFloat = 0, sb: CGFloat = 0, sa: CGFloat = 0
        var er: CGFloat = 0, eg: CGFloat = 0, eb: CGFloat = 0, ea: CGFloat = 0
        let components: [CGFloat]
        guard startColor.getRed(&sr, green: &sg, blue: &sb, alpha: &sa) && endColor.getRed(&er, green: &eg, blue: &eb, alpha: &ea) else {
            return nil
        }
        components = [sr, sg, sb, sa,
                      er, eg, eb, ea,
                      1.0, 1.0, 1.0, 1.0]
        return components
    }
}
